import { Inject, Injectable, InternalServerErrorException } from '@nestjs/common'
import { FastifyRequest } from 'fastify'
import { MODULE_OPTIONS_TOKEN } from '../cdncord.module-definition'
import { CdncordOptions } from '../interfaces/cdncord-options.interface'
import { createWebhookApp, MessageAttachmentConstructor, WebhookClient } from 'discordoo'
import { ErrorCodes } from '@boticord/consts'

type UploadedFile = {
  /** file name */
  name: string
  /** A function to move the file elsewhere on your server */
  mv(path: string, callback: (error: unknown) => void): void
  mv(path: string): Promise<void>
  /** Encoding type of the file */
  encoding: string
  /** The mimetype of your file */
  mimetype: string
  /** A buffer representation of your file, returns empty buffer in case useTempFiles option was set to true. */
  data: Buffer
  /** A path to the temporary file in case useTempFiles option was set to true. */
  tempFilePath: string
  /** A boolean that represents if the file is over the size limit */
  truncated: boolean
  /** Uploaded size in bytes */
  size: number
  /** MD5 checksum of the uploaded file */
  md5: string
}

@Injectable()
export class CdncordService {
  constructor(
    @Inject(MODULE_OPTIONS_TOKEN) private readonly options: CdncordOptions,
  ) {
    this.webhook = createWebhookApp({
      token: options.webhookToken,
      id: options.webhookID,
    }).build()
  }

  private readonly webhook: WebhookClient

  async fromFastifyRequest(req: FastifyRequest, at: number) {
    const files = (req.raw as any).files as UploadedFile | UploadedFile[]
    if (Array.isArray(files)) {
      return this.upload(files[at].data)
    } else {
      return this.upload(files.data)
    }
  }

  async upload(file: Buffer, mime?: string) {
    // console.log('uploading file', file, mime)
    const upload = new MessageAttachmentConstructor({
      file,
      name: `upload.${mime && mime !== 'unknown' ? mime.split('/')[1] : 'png'}`,
    })

    const result = await this.webhook.messages.create(upload)

    if (!result) throw new InternalServerErrorException({ code: ErrorCodes.ThirdPartyFail })

    const attachment = result.attachments[0]
    return { url: attachment.url, proxy: attachment.proxy_url }
  }
}